#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "sql.h"
#include "dlgaddlabel.h"
#include <QLabel>
#include <QScrollArea>
#include <QFileInfo>
#include <QDir>
#include <QDebug>
#include <QStandardItemModel>
#include <QProcess>
#include <QDesktopServices>
#include <QUrl>
#include <QFileDialog>
#include <QToolBar>
#include <QSplitter>
#include <QTextCharFormat>
#include <QMenu>
#include <QToolTip>
#include <QMessageBox>
#include <QClipboard>
#include <QShortcut>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    , m_ptrSql(nullptr)
{
    ui->setupUi(this);

    //初始化数据库
    m_ptrSql = Sql::getInstance();
    m_ptrSql->init();

    //搜索时回车也触发搜索按钮
    QShortcut *keyR=new QShortcut(QKeySequence(Qt::Key_Return),this); //大键盘的回车键
    connect(keyR,SIGNAL(activated()),this,SLOT(on_ptnSearch_clicked()));
    QShortcut *keyE=new QShortcut(QKeySequence(Qt::Key_Enter),this);  //数字键盘的回车键
    connect(keyE,SIGNAL(activated()),this,SLOT(on_ptnSearch_clicked()));

    //设置tableWidget的几个属性
    tablewidgetTitle<<"序号"<<"书名"<<"类型"<<"标签类型"<<"全路径"<<"路径"<<"作者"<<"出版社"<<"出版年份"<<"ISBN号"<<"简介"; //表格标题固定
    tablewidgetColumnCount = tablewidgetTitle.size(); //表格列数
    ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); //只能选中行
    ui->tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);//限制一次只能选中一行，如果没有该限制，按ctrl可以选中多行
    ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);  //表格数据不能编辑
    ui->tableWidget->setContextMenuPolicy(Qt::CustomContextMenu);         //右键显示，也可在ui中设置
    ui->tableWidget->setMouseTracking(true);  //鼠标追踪，鼠标悬停到单元格上时显示内容，也可在ui中设置

    //左侧treewidget的父节点先显示
    treeWidgetParentNodeShow();

    //删除dockWidget控件中的标题栏
    QWidget *widget = new QWidget;
    delete ui->dockWidgetLeft->titleBarWidget();
    ui->dockWidgetLeft->setTitleBarWidget(widget);
    //去除dockWidget的四周的边距，里面的控件会贴着边放置
    //ui->dockWidgetLeft->setWidget(ui->treeWidget);

    //给工具栏添加控件
    QToolBar *toolBar = new QToolBar(this);
    toolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); //设置工具栏中控件的文字显示在图标下方
    toolBar->setMovable(false);  //工具栏不可移动
    addToolBar(Qt::TopToolBarArea, toolBar);
    QAction *addPathAction = new QAction(QIcon(":/image/folderPlus.png"),"添加路径");
    toolBar->addAction(addPathAction);
    QAction *reloadAction = new QAction(QIcon(":/image/mainwidgetLoad.png"),"重新载入");
    toolBar->addAction(reloadAction);
    QAction *showAllDataAction = new QAction(QIcon(":/image/mainwidgetDisplay.png"),"显示全部");
    toolBar->addAction(showAllDataAction);
    QAction *clearNotExistDataAction = new QAction(QIcon(":/image/mainwidgetClearNotExist.png"),"清理数据");
    toolBar->addAction(clearNotExistDataAction);
    QAction *clearAllDataAction = new QAction(QIcon(":/image/mianwidgetClear.png"),"清空数据");
    toolBar->addAction(clearAllDataAction);

    //"添加路径"，弹出相应窗口
    connect(addPathAction,&QAction::triggered,this,[&](){
        m_eBookPath.firstShow();
        m_eBookPath.show();
    });
    //"重新载入"，根据选定的文件类型，从添加的路径中重新添加文件到数据表ebook，并显示
    connect(reloadAction,&QAction::triggered,this,&MainWindow::reloadData);
    //"显示全部"，直接从数据表ebook重载获取数据并显示
    connect(showAllDataAction,&QAction::triggered,this,&MainWindow::showData);
    //"清理数据"，清除数据表ebook中已经在本地不存在的文件信息
    connect(clearNotExistDataAction,&QAction::triggered,this,&MainWindow::clearNotExistData);
    //"清空数据"，弹窗警示，将清空所有数据请谨慎操作，如果确定清空，则将清空所有数据
    connect(clearAllDataAction,&QAction::triggered,this,&MainWindow::clearAllData);


    //单击选中tableWidget中的内容时，在界面下方显示简要信息
    connect(ui->tableWidget,SIGNAL(cellClicked(int, int)),this,SLOT(tableWidgetSelectRow(int,int)));
    //双击tableWidget内容时的一些操作，双击书名所在单元格打开文档，双击标签所在单元格弹窗增删标签，双击文件路径所在单元格打开文件所在路径
    connect(ui->tableWidget,SIGNAL(cellDoubleClicked(int, int)),this,SLOT(tableCellDoubleClickOperation(int,int)));
    //鼠标追踪，鼠标悬停在单元格上时，显示单元格内容
    connect(ui->tableWidget, SIGNAL(entered(QModelIndex)),this,SLOT(tabelWidgetTooltip(QModelIndex)));

    //双击左边treeWidget的项时，相当于搜索，如双击pdf (3)，表格刷新只显示pdf文档
    connect(ui->treeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),this,SLOT(treeSearchShow(QTreeWidgetItem*, int)));


    //在添加路径界面加载文件成功
    connect(&m_eBookPath,&EbookPath::loadFileSuccess,this,&MainWindow::showData);


    //点击添加标签时，将添加的标签信息获取出来
    connect(&m_addLabel, SIGNAL(sendLabelData(QStringList)),this,SLOT(updateBookLabel(QStringList)));
    //点击添加简介时，将添加的标签信息获取出来
    connect(&m_addIntro, SIGNAL(sendIntroData(QString)),this,SLOT(updateBookIntro(QString)));

    //修改信息，确认修改后进行刷新显示
    connect(&m_modifyInfo,SIGNAL(modifyConfirm(EbookInfo)),this,SLOT(modifyConfirmedShow(EbookInfo)));

    //批量修改，确认修改后进行保存和刷新显示处理
    connect(&m_batchModify,SIGNAL(sendModifyTableData(QList<EbookInfo>,int)),this,SLOT(getModifyTableData(QList<EbookInfo>, int)));

    //从csv文件导入数据，确认导入后进行保存和刷新显示处理
    connect(&m_importFromcsv,SIGNAL(sendImportData(QList<EbookInfo>)),this,SLOT(getImportData(QList<EbookInfo>)));

    //在没有选中tableWidget中的内容时，添加标签、添加简介按钮为不可用
    ui->ptnAddLabel->setEnabled(false);
    ui->ptnAddIntroduction->setEnabled(false);

    //不判空，在没有数据情况下第一次启动会先弹showData中的警告弹窗
    if (!m_ptrSql->getBookinfo().isEmpty())
    {
        showData();
    }
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::tabelWidgetShow(QList<EbookInfo> bookInfoList, int rowNum)
{
    //在单击时在界面下方显示；文件所在路径不显示，显示完整路径即可
    ui->tableWidget->setRowCount(0);
    ui->tableWidget->setColumnCount(0);
    ui->tableWidget->clearContents();
    ui->tableWidget->clear();
    ui->tableWidget->setColumnCount(tablewidgetColumnCount);
    ui->tableWidget->setHorizontalHeaderLabels(tablewidgetTitle);
    ui->tableWidget->setColumnWidth(0,38);
    ui->tableWidget->setColumnWidth(1,380);

    //根据数量将数据显示
    ui->tableWidget->setRowCount(rowNum);
    for (int i = 0; i < bookInfoList.size(); ++i)
    {
        ui->tableWidget->setItem(i,0,new QTableWidgetItem(QString::number(i+1)));
        ui->tableWidget->setItem(i,1,new QTableWidgetItem(bookInfoList[i].bookname));
        ui->tableWidget->setItem(i,2,new QTableWidgetItem(bookInfoList[i].booktype));
        ui->tableWidget->setItem(i,3,new QTableWidgetItem(bookInfoList[i].booklabel));
        ui->tableWidget->setItem(i,4,new QTableWidgetItem(bookInfoList[i].bookpath));
        ui->tableWidget->setItem(i,5,new QTableWidgetItem(bookInfoList[i].bookdir));
        ui->tableWidget->setItem(i,6,new QTableWidgetItem(bookInfoList[i].author));
        ui->tableWidget->setItem(i,7,new QTableWidgetItem(bookInfoList[i].publisher));
        ui->tableWidget->setItem(i,8,new QTableWidgetItem(bookInfoList[i].publishyear));
        ui->tableWidget->setItem(i,9,new QTableWidgetItem(bookInfoList[i].bookisbn));
        ui->tableWidget->setItem(i,10,new QTableWidgetItem(bookInfoList[i].bookintroduction));
    }

    ui->labelNum->setText(QString("数目：%1").arg(rowNum));
}

void MainWindow::treeWidgetParentNodeShow()
{
    //界面左侧树形控件三个父节点显示
    ui->treeWidget->setColumnCount(1);
    pBookType = new QTreeWidgetItem(ui->treeWidget,QStringList("文件类型"));
    pBookDir = new QTreeWidgetItem(ui->treeWidget,QStringList("文件路径"));
    pBookLabel = new QTreeWidgetItem(ui->treeWidget,QStringList("标签分类"));
    ui->treeWidget->addTopLevelItem(pBookType);
    ui->treeWidget->addTopLevelItem(pBookDir);
    ui->treeWidget->addTopLevelItem(pBookLabel);
    ui->treeWidget->expandAll();
}

void MainWindow::treeWidgetShow()
{
    //在界面左侧treewidget显示相关信息，
    quint32 count = 0;
    //添加子节点前清空所有子节点
    QList<QTreeWidgetItem*> pBookTypeChildren = pBookType->takeChildren();
    for (QTreeWidgetItem* child : pBookTypeChildren)
    {
        pBookType->removeChild(child);
    }
    QList<QTreeWidgetItem*> pBookDirChildren = pBookDir->takeChildren();
    for (QTreeWidgetItem* child : pBookTypeChildren)
    {
        pBookDir->removeChild(child);
    }
    QList<QTreeWidgetItem*> pBookLabelChildren = pBookLabel->takeChildren();
    for (QTreeWidgetItem* child : pBookLabelChildren)
    {
        pBookLabel->removeChild(child);
    }

    //根据文件类型显示对应的数量，如pdf (3)
    QStringList bookTypeList = m_ptrSql->getBookTypeList();
    for (QString bookType : bookTypeList)
    {
        count = m_ptrSql->getBookCount("booktype", bookType);
        QTreeWidgetItem *pPdf = new QTreeWidgetItem(pBookType,QStringList(QString("%1 (%2)").arg(bookType).arg(count)));
        pBookType->addChild(pPdf);
    }

    //根据文件路径显示对应路径下文件的数量，如E:/learning/C (8)
    QList<QString> bookDirList = m_ptrSql->getBookDirList();
    for (QString bookDir : bookDirList)
    {
        count = m_ptrSql->getBookCount("bookdir", bookDir);
        QTreeWidgetItem *pPdf = new QTreeWidgetItem(pBookDir,QStringList(QString("%1 (%2)").arg(bookDir).arg(count)));
        pBookDir->addChild(pPdf);
    }

    //根据标签类型显示
    QList<QString> bookLabelList = m_ptrSql->getBookLabelList();
    for (QString label : bookLabelList)
    {
        count = m_ptrSql->getBookCount("booklabel",label);
        QTreeWidgetItem *pPdf = new QTreeWidgetItem(pBookLabel,QStringList(QString("%1 (%2)").arg(label).arg(count)));
        pBookLabel->addChild(pPdf);
    }
}

void MainWindow::openFileDir(QString filepath)
{
    const QString explorer = "explorer";
    QStringList param;
    if (QFileInfo(filepath).isFile())
    {
        param << QLatin1String("/select,");
    }
    param << QDir::toNativeSeparators(filepath);
    QProcess::startDetached(explorer, param);
}

void MainWindow::showData()
{
    QList<EbookInfo> bookInfoList = m_ptrSql->getBookinfo();
    //qDebug() << "bookInfoList.size=" << bookInfoList.size();

    if (bookInfoList.isEmpty() && !m_isImportFromcsv)
    {
        //初始都为空，第一次启动会先弹该窗口，才会出现主窗口，在上面进行判断处理，这里有其他作用
        QMessageBox::information(this,tr("信息"),tr("数据为空，请先添加数据"));
        return;
    }

    //获取书籍总数量
    quint32 bookNum =  m_ptrSql->getAllBookNum();

    //在tabelwidget显示出来
    tabelWidgetShow(bookInfoList, bookNum);

    //在左侧treewidget显示相关信息
    treeWidgetShow();

    ui->ptnAddLabel->setEnabled(false);
    ui->ptnAddIntroduction->setEnabled(false);
    ui->textEditShow->clear();
    //清空全局变量
    m_filepath.clear();
    m_tableInfoMap.clear();
}

void MainWindow::clearData()
{
    m_ptrSql->clearBooktype();
    m_ptrSql->clearEbook();
    ui->textEditShow->clear();
    ui->labelNum->clear();

    //m_ptrSql->clearBookDir(); //存路径的数据表不在这里清空，调用"添加路径"窗口里的函数清空
    m_eBookPath.clearAll();     //清空bookdir数据表，调用"添加路径"窗口里的函数清空

    ui->tableWidget->setRowCount(0);
    ui->tableWidget->setColumnCount(0);
    ui->tableWidget->clearContents();
    ui->tableWidget->clear();

    //清空数据，不清treewidget的三个父节点
    ui->treeWidget->clear();
    treeWidgetParentNodeShow();

    ui->ptnAddLabel->setEnabled(false);
    ui->ptnAddIntroduction->setEnabled(false);

    //清空全局变量
    m_filepath.clear();
    m_tableInfoMap.clear();
}

void MainWindow::clearAllData()
{
    QMessageBox msgBox(QMessageBox::Warning, tr("警告"),tr("该操作将清空所有数据，请谨慎操作，确定要执行清空操作吗？")
                       ,QMessageBox::Yes|QMessageBox::No,this);
    QMessageBox msgBoxSecond(QMessageBox::Warning, tr("警告"),tr("确定要执行清空操作吗？")
                       ,QMessageBox::Yes|QMessageBox::No,this);
    if (msgBox.exec() == QMessageBox::Yes && msgBoxSecond.exec() == QMessageBox::Yes)
    {
        clearData();
        QMessageBox::information(this,tr("信息"),tr("数据已全部清空"));
    }
}

//清理已经不在本地的文件记录
void MainWindow::clearNotExistData()
{
    QMessageBox msgBox(QMessageBox::Warning, tr("警告"),tr("该操作将清理数据表中保存的但本地已经不存在了的文件的信息，确定要执行该操作吗？")
                       ,QMessageBox::Yes|QMessageBox::No,this);
    if (msgBox.exec() == QMessageBox::Yes)
    {
        QList<EbookInfo> bookInfoList = m_ptrSql->getBookinfo();

        if (bookInfoList.isEmpty())
        {
            QMessageBox::information(this,tr("信息"),tr("数据表为空，无需清理"));
            return;
        }

        QStringList notExistPathList;
        for (EbookInfo book : bookInfoList)
        {
            QFile file(book.bookpath);
            if (!file.exists())
            {
                notExistPathList.append(book.bookpath);
            }
        }
        //qDebug() << "notExistPathList" << notExistPathList;

        if (!notExistPathList.isEmpty())
        {
            m_ptrSql->clearNotExistBook(notExistPathList);
            QString clearPath = "";
            for (int i = 0; i < notExistPathList.size(); ++i)
            {
                clearPath.append(notExistPathList[i]);
                if (i != notExistPathList.size()-1)
                {
                    clearPath.append("; ");
                }
            }
            QMessageBox::information(this,tr("信息"),QString("已清理本地已不存在的数据表信息：%1").arg(clearPath));
            //清理后重新显示
            ui->treeWidget->clear();
            treeWidgetParentNodeShow();
            showData();
            ui->ptnAddLabel->setEnabled(false);
            ui->ptnAddIntroduction->setEnabled(false);
            ui->textEditShow->clear();
        }
        else
        {
            QMessageBox::information(this,tr("信息"),tr("数据表中保存的文件信息在本地都存在，无需清理"));
        }
    }
}

void MainWindow::reloadData()
{
    QVector<QString> dirVec = m_ptrSql->getBookDir();
    QStringList booktypeList = m_ptrSql->getBooktype();
    EbookInfo ebook;
    QList<EbookInfo> ebookList;

//    qDebug() << "dirvec=" <<dirVec;
//    qDebug() << "booktype=" << booktypeList;

    for (QString dirStr : dirVec)
    {
        QDir dir(dirStr);
        for(QFileInfo info : dir.entryInfoList(QDir::NoDotAndDotDot | QDir::Files))
        {
            QString fileName = info.fileName();
            QString filePath = info.filePath();
            QString suffix = info.suffix().toLower();
            if (booktypeList.size() > 0) //如果不为空，表示根据选定的文件类型从路径中添加文件
            {
                if (booktypeList.contains(suffix))
                {
                    ebook.bookname = fileName;
                    ebook.booktype = suffix;
                    ebook.bookpath = filePath;
                    ebook.bookdir = dirStr;
                    ebookList.push_back(ebook);
                }
            }
            else  //如果为空，表示不限定类型，只要是文件都添加到数据表ebook
            {
                ebook.bookname = fileName;
                ebook.booktype = suffix;
                ebook.bookpath = filePath;
                ebook.bookdir = dirStr;
                ebookList.push_back(ebook);
            }
        }
    }

    if (ebookList.size() > 0)
    {
        m_ptrSql->addBookinfo(ebookList);
        //重新加载后重新显示出来
        ui->treeWidget->clear();
        treeWidgetParentNodeShow();
        showData();
        //在没有选中tableWidget中的内容时，添加标签、添加简介按钮为不可用
        ui->ptnAddLabel->setEnabled(false);
        ui->ptnAddIntroduction->setEnabled(false);
        ui->textEditShow->clear();
        //清空全局变量
        m_filepath.clear();
        m_tableInfoMap.clear();

        QString typeStr;
        if (booktypeList.size() > 0)
        {
            for (int i = 0; i < booktypeList.size(); ++i)
            {
                typeStr.append(booktypeList[i]);
                if (i != booktypeList.size()-1)
                {
                    typeStr.append(",");
                }
            }
        }
        else
        {
            typeStr="不限类型";
        }

        QString dirStr;
        for (int i = 0; i < dirVec.size(); ++i)
        {
            dirStr.append(dirVec[i]);
            if (i != dirVec.size()-1)
            {
                dirStr.append(",");
            }
        }
        QMessageBox::information(this,tr("信息"),QString("已根据选定文件类型从本地路径重新载入文件信息，"
                                                       "选定的类型：%1，已添加的本地路径：%2").arg(typeStr).arg(dirStr));
    }
    else
    {
        QMessageBox::warning(this,tr("警告"),tr("数据表为空，请先添加路径并载入数据"));
    }
}

void MainWindow::tableWidgetSelectRow(int row, int col)
{
    if (row < 0 || col < 0)
    {
        return;
    }

    EbookInfo bookInfo;
    //选中tablewidget中的内容时，添加标签、添加简介按钮设置可用
    ui->ptnAddLabel->setEnabled(true);
    ui->ptnAddIntroduction->setEnabled(true);

    bookInfo.bookname = ui->tableWidget->item(row,1)->text();
    bookInfo.booklabel = ui->tableWidget->item(row,3)->text();
    bookInfo.bookpath = ui->tableWidget->item(row,4)->text();
    bookInfo.bookintroduction = ui->tableWidget->item(row,10)->text();

    bookInfoShow(bookInfo);

    m_filepath = bookInfo.bookpath;
    m_bookInfo = bookInfo;

    //单击选中一行时，将全部信息存成map，存在全局变量中
    m_tableInfoMap.clear();
    for (int i = 0; i < tablewidgetColumnCount; ++i)
    {
        m_tableInfoMap.insert(tablewidgetTitle[i], ui->tableWidget->item(row,i)->text());
    }
}

void MainWindow::tableCellDoubleClickOperation(int row, int col)
{
    if (row < 0)
    {
        return;
    }

    //qDebug() << "doubleClick,row="<<row<<",col="<<col;

    QString bookpath = ui->tableWidget->item(row,4)->text();
    QFile file(bookpath);
    if (!file.exists())
    {
        QMessageBox::warning(this,"警告",QString("该文件<%1>本地已不存在，请执行[清理数据]操作").arg(bookpath));
        return;
    }

    //第二列(col是1)是书名，表示双击书名单元格打开文件，使用默认程序打开(win系统)
    if (1 == col)
    {
        QDesktopServices::openUrl(QUrl::fromLocalFile(bookpath));
    }

    //第四列(col是3)是标签，双击可以进行增删，跟界面下方的增删按钮功能一样
    if (3 == col)
    {
        on_ptnAddLabel_clicked();  //直接调槽函数
    }

    //第五列(col是4)是全路径，双击进入路径并高亮选中文件
    if(4 == col)
    {
        openFileDir(bookpath);
    }
}

//鼠标悬停在单元格中时显示单元格内容，对显示全路径尤其有用
void MainWindow::tabelWidgetTooltip(QModelIndex index)
{
    QToolTip::showText(QCursor::pos(),index.data().toString());
}

void MainWindow::treeSearchShow(QTreeWidgetItem *treeItem, int n)
{
    QTreeWidgetItem* p = treeItem->parent();
    if (p != nullptr)
    {
        //多放几个变量吧，阅读清楚
        QList<EbookInfo> bookInfoList;
        int count = 0;

        QString str = treeItem->text(n);
        QString sp = str.mid(0,str.lastIndexOf("("));
        QString itemStr = sp.trimmed();
        QString parentStr = p->text(n);
        //qDebug() << "treeSearchShow-n="<<n <<",str="<<str <<",sp="<<sp <<",itemStr="<<itemStr<< ",parent="<<parentStr;

        //根据双击treewidget选中的项，查询数据库，并显示
        if ("文件类型" == parentStr)
        {
            bookInfoList = m_ptrSql->getBookinfoBasisToType("booktype",itemStr);
            count = m_ptrSql->getBookCount("booktype", itemStr);
        }
        else if ("文件路径" == parentStr)
        {
            bookInfoList = m_ptrSql->getBookinfoBasisToType("bookdir",itemStr);
            count = m_ptrSql->getBookCount("bookdir", itemStr);
        }
        else  //"标签分类" == parentStr
        {
            bookInfoList = m_ptrSql->getBookinfoBasisToType("booklabel",itemStr);
            count = m_ptrSql->getBookCount("booklabel", itemStr);
        }

        //显示在表格中
        tabelWidgetShow(bookInfoList, count);
        ui->ptnAddLabel->setEnabled(false);
        ui->ptnAddIntroduction->setEnabled(false);
        ui->textEditShow->clear();
    }
}


void MainWindow::on_ptnAddLabel_clicked()
{
    m_addLabel.showLabel(m_bookInfo.booklabel);
    m_addLabel.show();
}

void MainWindow::on_ptnAddIntroduction_clicked()
{
    m_addIntro.showIntro(m_bookInfo.bookintroduction);
    m_addIntro.show();
}

//添加标签时调用更新数据库
void MainWindow::updateBookLabel(QStringList labelList)
{
    QString labelStr;
    for (int i = 0; i < labelList.size(); ++i)
    {
        labelStr.append(labelList[i]);
        if (i != labelList.size()-1)
        {
            labelStr.append(";");
        }
    }

    m_bookInfo.booklabel = labelStr;
    //更新数据库
    //qDebug() << "booklabel=" << labelStr << ",update-bookpath=" <<m_bookInfo.bookpath;
    m_ptrSql->updateBookInfoBasisToType("booklabel",labelStr,m_bookInfo.bookpath);

    //更新表格显示，整个表格刷新，整个左侧treewidget刷新，简单粗暴
    showData();

    //更新表格下方的显示，即书名、标签、简介的简要显示
    bookInfoShow(m_bookInfo);
}

void MainWindow::updateBookIntro(QString strIntro)
{
    //qDebug() << "add-strIntro=" << strIntro;
    m_bookInfo.bookintroduction = strIntro;
    //更新数据库
    //qDebug() << "bookintroduction=" << strIntro << ",update-bookpath=" <<m_bookInfo.bookpath;
    m_ptrSql->updateBookInfoBasisToType("bookintroduction",strIntro,m_bookInfo.bookpath);

    //更新表格显示，整个表格刷新，简单粗暴
    showData();

    //更新表格下方的显示，即书名、标签、简介的简要显示
    bookInfoShow(m_bookInfo);
}

void MainWindow::bookInfoShow(EbookInfo bookInfo)
{
    ui->textEditShow->clear();
    QTextCharFormat fmt;
    fmt.setForeground(Qt::blue);
    ui->textEditShow->setCurrentCharFormat(fmt);
    ui->textEditShow->append(tr("书名："));

    fmt.setForeground(Qt::black);
    ui->textEditShow->setCurrentCharFormat(fmt);
    ui->textEditShow->append(bookInfo.bookname);

    fmt.setForeground(Qt::blue);
    ui->textEditShow->setCurrentCharFormat(fmt);
    ui->textEditShow->append(tr("标签："));

    fmt.setForeground(Qt::black);
    ui->textEditShow->setCurrentCharFormat(fmt);
    ui->textEditShow->append(bookInfo.booklabel);

    fmt.setForeground(Qt::blue);
    ui->textEditShow->setCurrentCharFormat(fmt);
    ui->textEditShow->append(tr("全路径："));

    fmt.setForeground(Qt::black);
    ui->textEditShow->setCurrentCharFormat(fmt);
    ui->textEditShow->append(bookInfo.bookpath);

    fmt.setForeground(Qt::blue);
    ui->textEditShow->setCurrentCharFormat(fmt);
    ui->textEditShow->append(tr("简介："));

    fmt.setForeground(Qt::black);
    ui->textEditShow->setCurrentCharFormat(fmt);
    ui->textEditShow->append(bookInfo.bookintroduction);

    ui->textEditShow->moveCursor(QTextCursor::Start); //显示完后光标移到开头
}

//表格右键弹出菜单
void MainWindow::on_tableWidget_customContextMenuRequested(const QPoint &pos)
{
    int x = pos.x();
    int y = pos.y();
    QModelIndex index = ui->tableWidget->indexAt(QPoint(x,y));
    int row = index.row();
    int col = index.column();
    //qDebug() << "x="<<x<<",y="<<y<<",row="<<row<<",col="<<col;

    //点击右键时，也将全部信息存成map，存在全局变量中
    m_tableInfoMap.clear();
    for (int i = 0; i < tablewidgetColumnCount; ++i)
    {
        m_tableInfoMap.insert(tablewidgetTitle[i], ui->tableWidget->item(row,i)->text());

    }
    //点击右键时，也显示在界面下方
    //选中tablewidget中的内容时，添加标签、添加简介按钮设置可用
    ui->ptnAddLabel->setEnabled(true);
    ui->ptnAddIntroduction->setEnabled(true);
    EbookInfo bookInfo;
    bookInfo.bookname = ui->tableWidget->item(row,1)->text();
    bookInfo.booklabel = ui->tableWidget->item(row,3)->text();
    bookInfo.bookpath = ui->tableWidget->item(row,4)->text();
    bookInfo.bookintroduction = ui->tableWidget->item(row,10)->text();

    bookInfoShow(bookInfo);

    //存到全部变量
    m_filepath = bookInfo.bookpath;
    m_bookInfo = bookInfo;

    QMenu *menu = new QMenu(ui->tableWidget);

    QAction *openFile = menu->addAction(tr("打开文件"));
    QAction *openFilePath = menu->addAction(tr("打开文件所在路径"));
    QAction *copy = menu->addAction(tr("复制该单元格内容"));
    QAction *copyLine = menu->addAction(tr("复制该行内容"));
    QAction *modifyInfo = menu->addAction(tr("修改信息"));

    connect(openFile, &QAction::triggered, [=](){
        tableWidgetMenuRequestedOpenFile(row);
    });

    connect(openFilePath, &QAction::triggered, [=](){
        tableWidgetMenuRequestedOpenFilePath(row);
    });

    connect(copy, &QAction::triggered, [=](){
        tableWidgetMenuRequestedCopy(row, col);
    });

    connect(copyLine, &QAction::triggered, [=](){
        tableWidgetMenuRequestedCopyLine(row);
    });

    connect(modifyInfo, &QAction::triggered, [=](){
        tableWidgetMenuRequestedModifyInfo(row);
    });

    menu->exec(QCursor::pos());

    //释放内存
    QList<QAction*> list = menu->actions();
    for (auto action : list)
    {
        delete action;
    }
    delete menu;
}

void MainWindow::tableWidgetMenuRequestedOpenFile(int row)
{
    if (-1 != row)
    {
        QString bookpath = ui->tableWidget->item(row,4)->text();
        if (!bookpath.isEmpty())
        {
            QDesktopServices::openUrl(QUrl::fromLocalFile(bookpath));
        }
        else
        {
            QMessageBox::warning(this,"警告","文件名为空或文件已不存在，请先选择表格中的一行或执行[清理数据]操作");
        }
    }
}

void MainWindow::tableWidgetMenuRequestedOpenFilePath(int row)
{
    if (-1 != row)
    {
        QString bookpath = ui->tableWidget->item(row,4)->text();
        //bookpath = "E:\\cc.pdf";
        QFile file(bookpath);
        if (file.exists())
        {
            openFileDir(bookpath);
        }
        else
        {
            QMessageBox::warning(this,"警告",QString("文件已不存在：%1，执行[清理数据]操作").arg(bookpath));
        }
    }
}

void MainWindow::tableWidgetMenuRequestedCopy(int row, int col)
{
    if (row < 0 || col < 0)
    {
        QMessageBox::warning(this,"警告","请选中单元格");
        return;
    }

    QString itemStr = ui->tableWidget->item(row,col)->text();
    if (itemStr.length() > 0)
    {
        QClipboard *board = QApplication::clipboard();
        board->setText(itemStr);
        QMessageBox::information(this,"信息",QString("已复制至剪贴板：%1").arg(itemStr));
        //qDebug() << "board-itemStr="<<itemStr;
    }
    else
    {
        QMessageBox::warning(this,"警告","该单元格内容为空");
    }
}

void MainWindow::tableWidgetMenuRequestedCopyLine(int row)
{
    if (row < 0)
    {
        QMessageBox::warning(this,"警告","请选中表格中的一行");
        return;
    }

    QString tabelLine = getTableLineStr(row); //获取表格选中的行的内容
    QClipboard *board = QApplication::clipboard();
    board->setText(tabelLine);
    QMessageBox::information(this,"信息",QString("已复制至剪贴板：%1").arg(tabelLine));
    //qDebug() << "tabelLine="<<tabelLine;
}

void MainWindow::tableWidgetMenuRequestedModifyInfo(int row)
{
    if (row < 0)
    {
        QMessageBox::warning(this,"警告","请选中表格中的一行");
        return;
    }

    QMap<QString,QString> infoMap;
    for (int i = 0; i < tablewidgetColumnCount; ++i)
    {
        infoMap.insert(tablewidgetTitle[i], ui->tableWidget->item(row,i)->text());
    }
    m_modifyInfo.showInfo(infoMap);
    m_modifyInfo.show();
}

//修改信息后，刷新数据显示
void MainWindow::modifyConfirmedShow(EbookInfo bookInfo)
{
    //更新表格显示，整个表格刷新，简单粗暴
    showData();

    //更新表格下方的显示，即书名、标签、简介的简要显示
    bookInfoShow(bookInfo);
}

//获取表格中一行的内容
QString MainWindow::getTableLineStr(int row)
{
    QString tabelLine;
    for (int i = 0; i < tablewidgetColumnCount; ++i)
    {
        tabelLine.append(tablewidgetTitle[i]+":");
        tabelLine.append(ui->tableWidget->item(row,i)->text());
        if (i != tablewidgetColumnCount-1)
        {
            tabelLine.append("; ");
        }
    }
    return tabelLine;
}


void MainWindow::on_ptnOpenFile_clicked()
{
    if (!m_filepath.isEmpty())
    {
        QDesktopServices::openUrl(QUrl::fromLocalFile(m_filepath));
    }
    else
    {
        QMessageBox::warning(this,"警告","文件名为空或文件已不存在，请先选择表格中的一行或执行[清理数据]操作");
    }
}

void MainWindow::on_ptnOpenFilePath_clicked()
{
    if (!m_filepath.isEmpty())
    {
        QFile file(m_filepath);
        if (file.exists())
        {
            openFileDir(m_filepath);
        }
        else
        {
            QMessageBox::warning(this,"警告",QString("文件已不存在：%1，执行[清理数据]操作").arg(m_filepath));
        }
    }
    else
    {
        QMessageBox::warning(this,"警告","路径为空，请先选择表格中的一行");
    }
}

void MainWindow::on_ptnModifyBookInfo_clicked()
{
    if (!m_tableInfoMap.isEmpty())
    {
        m_modifyInfo.showInfo(m_tableInfoMap);
        m_modifyInfo.show();
    }
    else
    {
        QMessageBox::warning(this,"警告","请选中表格中的一行");
    }
}

void MainWindow::on_ptnSearch_clicked()
{
    QString strSearch = ui->lineEditSearch->text();
    if (strSearch.isEmpty())
    {
        QMessageBox::warning(this,"警告","输入为空，请输入要查询的书名关键词");
        return;
    }

    QList<EbookInfo> searchResBookInfoList;
    EbookInfo bookinfo;

    int rowNumber = ui->tableWidget->rowCount();
    int searchNum = 0;
    //qDebug() << "rowNumber="<<rowNumber;
    for(int i = 0; i < rowNumber; ++i)
    {
        QString bookname = ui->tableWidget->item(i,1)->text();//书名列
        //qDebug() << "bookname="<<bookname;
        if (bookname.contains(strSearch))
        {
            bookinfo.bookname = ui->tableWidget->item(i,1)->text();
            bookinfo.booktype = ui->tableWidget->item(i,2)->text();
            bookinfo.booklabel = ui->tableWidget->item(i,3)->text();
            bookinfo.bookpath = ui->tableWidget->item(i,4)->text();
            bookinfo.bookdir = ui->tableWidget->item(i,5)->text();
            bookinfo.author = ui->tableWidget->item(i,6)->text();
            bookinfo.publisher = ui->tableWidget->item(i,7)->text();
            bookinfo.publishyear = ui->tableWidget->item(i,8)->text();
            bookinfo.bookisbn = ui->tableWidget->item(i,9)->text();
            bookinfo.bookintroduction = ui->tableWidget->item(i,10)->text();
            searchResBookInfoList.append(bookinfo);
            searchNum++;
        }
    }

    if (searchNum > 0)
    {
        tabelWidgetShow(searchResBookInfoList, searchNum);
        ui->ptnAddLabel->setEnabled(false);
        ui->ptnAddIntroduction->setEnabled(false);
        ui->textEditShow->clear();
    }
    else
    {
        QMessageBox::information(this,"信息","没有所查询书籍");
    }
}


void MainWindow::on_ptnImport_clicked()
{
    QString importTitleformat = "序号,null,书名,null,类型,null,标签类型,null,全路径,null,路径,null,作者,null,出版社,null,出版年份,null,ISBN号,null,简介";
    QMessageBox msgBox(QMessageBox::Information, tr("信息"),QString("该操作将从本地csv文件中导入数据，为了确保能够成功导入，请确保文件是utf8+bom编码，"
                                     "且请在csv文件中手动间隔增加一列包含null字段的列且该列中每行均写入null字串，确保csv文件中的列为<%1>").arg(importTitleformat)
                       ,QMessageBox::Yes|QMessageBox::No,this);
    if (msgBox.exec() == QMessageBox::Yes)
    {
        QString filename = QFileDialog::getOpenFileName(this,tr("从csv文件导入数据"),"",tr("*.csv"));
        QList<EbookInfo> bookinfoList;
        //qDebug() << "importFile="<<filename;
        if (!filename.isEmpty())
        {
            QFile file(filename);
            if(file.open(QIODevice::ReadOnly | QIODevice::Text))
            {
                QTextStream inStream(&file);

                QString titleLine;
                QString line;
                QStringList inBookinfoList;
                EbookInfo bookInfo;
                int num = 0;
                while(!inStream.atEnd())
                {
                    if (0 == num)
                    {
                        titleLine = inStream.readLine();
                        //qDebug() << "titleLine=" << titleLine;
                        if (titleLine != importTitleformat)
                        {
                            QMessageBox::critical(this,"错误", QString("csv文件格式不正确，要导入的csv文件应包含如下的列信息：<%1>, 您所选csv文件的列信息为：<%2>，"
                                                               "如出现乱码，为编码问题，请确保文件是utf8+bom编码").arg(importTitleformat).arg(titleLine));
                            file.close();
                            return;
                        }
                    }
                    else
                    {
                        line = inStream.readLine();
                        inBookinfoList = line.split(",null,");
                        if (inBookinfoList.size() != tablewidgetColumnCount)
                        {
                            QMessageBox::critical(this,"错误","导入失败，csv文件格式不正确");
                            file.close();
                            return;
                        }

                        //可能出现这种形式 \"深度探索C++对象模型(Stanley Lippman , 侯捷).pdf\"
                        QString resBookname = inBookinfoList[1];
                        if (inBookinfoList[1].split("\"").size() > 1)
                        {
                            resBookname = inBookinfoList[1].split("\"")[1];
                        }

                        QString resBookpath = inBookinfoList[4];
                        if (inBookinfoList[4].split("\"").size() > 1)
                        {
                            resBookpath = inBookinfoList[4].split("\"")[1];
                        }

                        QString resBookdir = inBookinfoList[5];
                        if (inBookinfoList[5].split("\"").size() > 1)
                        {
                            resBookdir = inBookinfoList[5].split("\"")[1];
                        }

                        bookInfo.numId = inBookinfoList[0].toInt();
                        bookInfo.bookname = resBookname;
                        bookInfo.booktype = inBookinfoList[2];
                        bookInfo.booklabel = inBookinfoList[3];
                        bookInfo.bookpath = resBookpath;
                        bookInfo.bookdir = resBookdir;
                        bookInfo.author = inBookinfoList[6];
                        bookInfo.publisher = inBookinfoList[7];
                        bookInfo.publishyear = inBookinfoList[8];
                        bookInfo.bookisbn = inBookinfoList[9];
                        bookInfo.bookintroduction = inBookinfoList[10];
                        bookinfoList.append(bookInfo);
                    }
                    num++;
                }
                file.close();
                //qDebug() << "in-num="<<num;
            }
            else
            {
                QMessageBox::critical(this,"错误",QString("导入失败，读取文件失败：%1").arg(filename));
                file.close();
                return;
            }
        }
        m_importFromcsv.tableDataShow(bookinfoList);
        m_importFromcsv.show();
    }
}

QList<EbookInfo> MainWindow::getCurrentTableData()
{
    QList<EbookInfo> resBookInfoList;
    EbookInfo bookinfo;
    int rowNumber = ui->tableWidget->rowCount();
    for(int i = 0; i < rowNumber; ++i)
    {
        bookinfo.numId = ui->tableWidget->item(i,0)->text().toInt();
        bookinfo.bookname = ui->tableWidget->item(i,1)->text();
        bookinfo.booktype = ui->tableWidget->item(i,2)->text();
        bookinfo.booklabel = ui->tableWidget->item(i,3)->text();
        bookinfo.bookpath = ui->tableWidget->item(i,4)->text();
        bookinfo.bookdir = ui->tableWidget->item(i,5)->text();
        bookinfo.author = ui->tableWidget->item(i,6)->text();
        bookinfo.publisher = ui->tableWidget->item(i,7)->text();
        bookinfo.publishyear = ui->tableWidget->item(i,8)->text();
        bookinfo.bookisbn = ui->tableWidget->item(i,9)->text();
        bookinfo.bookintroduction = ui->tableWidget->item(i,10)->text();
        resBookInfoList.append(bookinfo);
    }
    return resBookInfoList;
}

void MainWindow::on_ptnExport_clicked()
{
    QMessageBox msgBox(QMessageBox::Information, tr("信息"),tr("该操作将导出显示在表格中的数据，如果想导出全部数据请先点击[显示全部]按钮")
                       ,QMessageBox::Yes|QMessageBox::No,this);
    if (msgBox.exec() == QMessageBox::Yes)
    {
        QString filename = QFileDialog::getSaveFileName(this,tr("保存为csv"), QDir::currentPath(),tr("*.csv"));
        if (filename.isEmpty())
        {
            return;
        }
        else
        {
            QList<EbookInfo> exportResBookInfoList = getCurrentTableData();
            QFile file(filename);
            if (file.exists())
            {
                QMessageBox msgBox(QMessageBox::Warning, tr("警告"),
                                   QString("文件<%1>已存在，继续保存将删除该文件的原有数据，确定要覆盖该文件吗？").arg(filename),
                                   QMessageBox::Yes|QMessageBox::No,this);
                if(msgBox.exec() == QMessageBox::Yes)
                {
                    file.remove(); //删除存在的数据
                }
                else
                {
                    return;
                }
            }

            QTextStream outStream(&file);
            outStream.setGenerateByteOrderMark(true); //设置带BOM的utf8，不然使用excel打开导出的csv会显示乱码
            outStream.setCodec("UTF-8");
            outStream << tr("序号,") << tr("书名,") << tr("类型,") << tr("标签类型,") << tr("全路径,") << tr("路径,")
                       << tr("作者,") << tr("出版社,") << tr("出版年份,") << tr("ISBN号,") << tr("简介") << "\n";
            if (file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append))
            {
                ui->statusbar->showMessage(tr("正在导出数据......"));
                for (auto book:exportResBookInfoList)
                {

                    outStream << book.numId;
                    outStream << ",";
                    outStream << QString("\""+book.bookname+"\""); //bookname有空格会出问题，用双引号括注
                    outStream << ",";
                    outStream << QString("\""+book.booktype+"\"");
                    outStream << ",";
                    outStream << QString("\""+book.booklabel+"\"");
                    outStream << ",";
                    outStream << QString("\""+book.bookpath+"\"");
                    outStream << ",";
                    outStream << QString("\""+book.bookdir+"\"");
                    outStream << ",";
                    outStream << QString("\""+book.author+"\"");
                    outStream << ",";
                    outStream << QString("\""+book.publisher+"\"");
                    outStream << ",";
                    outStream << QString("\""+book.publishyear+"\"");
                    outStream << ",";
                    outStream << QString("\""+book.bookisbn+"\"");
                    outStream << ",";
                    outStream << QString("\""+book.bookintroduction+"\"");
                    outStream << "\n";
                }
                file.close();
                ui->statusbar->clearMessage();
                QMessageBox::information(this,"信息",QString("导出成功，导出的csv文件为utf8+bom编码，已保存到：%1").arg(filename));
            }
            else
            {
                //qDebug() << "write err";
                QMessageBox::critical(this,"错误",QString("导出失败，写入文件失败：%1").arg(filename));
                file.close();
            }
        }
    }
}

void MainWindow::on_ptnBatchModify_clicked()
{
    QMessageBox msgBox(QMessageBox::Information, tr("信息"),tr("该操作可批量修改显示在表格中的数据，如果想批量修改全部数据请先点击[显示全部]按钮")
                       ,QMessageBox::Yes|QMessageBox::No,this);
    if(msgBox.exec() == QMessageBox::Yes)
    {
        QList<EbookInfo> resBookInfoList = getCurrentTableData();
        m_batchModify.tableDataShow(resBookInfoList);
        m_batchModify.show();
    }
}

void MainWindow::getModifyTableData(QList<EbookInfo> resBookInfoList, int rowNum)
{
    //将数据更新到数据表
    for (auto book : resBookInfoList)
    {
        m_ptrSql->updateBookInfo(book);
    }

    //可能前面批量修改的不是全部数据，这里不使用showData()，使用单独模块的显示函数
    tabelWidgetShow(resBookInfoList,rowNum);
    treeWidgetShow();

    ui->ptnAddLabel->setEnabled(false);
    ui->ptnAddIntroduction->setEnabled(false);
    ui->textEditShow->clear();
    //清空全局变量
    m_filepath.clear();
    m_tableInfoMap.clear();
}

void MainWindow::getImportData(QList<EbookInfo> importBookinfoList)
{
    m_isImportFromcsv = true;
    //清空ebook、ebooktype、ebookdir数据表以及其他数据
    clearData();

    //将导入的数据添加到ebook数据表
    m_ptrSql->addBookinfo(importBookinfoList);

    //过滤文件类型，并将文件类型添加掉ebooktype数据表中
    QStringList importBooktype;
    for (EbookInfo bookinfo : importBookinfoList)
    {
        if (!importBooktype.contains(bookinfo.booktype))
        {
            importBooktype.append(bookinfo.booktype);
        }
    }
    m_ptrSql->addBooktype2db(importBooktype);

    //将文件路径添加到ebookdir数据表中
    QList<EbookInfo> bookList = m_ptrSql->getBookinfo();
    QVector<QString> importBookdir;
    for (EbookInfo bookinfo : bookList)
    {
        if (!importBookdir.contains(bookinfo.bookdir))
        {
            importBookdir.append(bookinfo.bookdir);
        }
    }
    m_ptrSql->addBookDir2db(importBookdir);

    //显示
    showData();
}
